<template>
  <div :class="wrapClasses">
    <template v-if="type !== 'textarea'">
      <div :class="[prefixCls + '-group-prepend']" v-if="prepend" v-show="slotReady">
        <slot name="prepend"></slot>
      </div>
      <i class="ivu-icon" :class="['ivu-icon-' + icon, prefixCls + '-icon', prefixCls + '-icon-normal']" v-if="icon"
         @click="handleIconClick"></i>
      <transition name="fade">
        <i class="ivu-icon ivu-icon-load-c ivu-load-loop" :class="[prefixCls + '-icon', prefixCls + '-icon-validate']"
           v-if="!icon"></i>
      </transition>
      <input
        ref="input"
        :type="type"
        :class="inputClasses"
        :placeholder="placeholder"
        :disabled="disabled"
        :maxlength="maxlength"
        :readonly="readonly"
        :name="name"
        :value="currentValue"
        :number="number"
        :autofocus="autofocus"
        @keyup.enter="handleEnter"
        @focus="handleFocus"
        @blur="handleBlur"
        @input="handleInput"
        @change="handleChange">
      <div :class="[prefixCls + '-group-append']" v-if="append" v-show="slotReady">
        <slot name="append"></slot>
      </div>
    </template>
    <textarea
      v-else
      ref="textarea"
      :class="textareaClasses"
      :style="textareaStyles"
      :placeholder="placeholder"
      :disabled="disabled"
      :rows="rows"
      :maxlength="maxlength"
      :readonly="readonly"
      :name="name"
      :value="value"
      @keyup.enter="handleEnter"
      @focus="handleFocus"
      @blur="handleBlur"
      @input="handleInput">
        </textarea>
  </div>
</template>
<script>
  import {oneOf, findComponentUpward} from '../../utils/assist';
  import calcTextareaHeight from '../../utils/calcTextareaHeight';
  import Emitter from '../../mixins/emitter';

  const prefixCls = 'oolong-input';

  export default {
    name: 'oolongInput',
    mixins: [Emitter],
    props: {
      type: {
        validator (value) {
          return oneOf(value, ['text', 'textarea', 'password']);
        },
        default: 'text'
      },
      value: {
        type: [String, Number],
        default: ''
      },
      size: {
        validator (value) {
          return oneOf(value, ['small', 'large']);
        }
      },
      placeholder: {
        type: String,
        default: ''
      },
      maxlength: {
        type: Number
      },
      disabled: {
        type: Boolean,
        default: false
      },
      icon: String,
      autosize: {
        type: [Boolean, Object],
        default: false
      },
      rows: {
        type: Number,
        default: 2
      },
      readonly: {
        type: Boolean,
        default: false
      },
      name: {
        type: String
      },
      number: {
        type: Boolean,
        default: false
      },
      autofocus: {
        type: Boolean,
        default: false
      }
    },
    data () {
      return {
        currentValue: this.value,
        prefixCls: prefixCls,
        prepend: true,
        append: true,
        slotReady: false,
        textareaStyles: {}
      };
    },
    computed: {
      wrapClasses () {
        return [
          `${prefixCls}-wrapper`,
          {
            [`${prefixCls}-wrapper-${this.size}`]: !!this.size,
            [`${prefixCls}-type`]: this.type,
            [`${prefixCls}-group`]: this.prepend || this.append,
            [`${prefixCls}-group-${this.size}`]: (this.prepend || this.append) && !!this.size,
            [`${prefixCls}-group-with-prepend`]: this.prepend,
            [`${prefixCls}-group-with-append`]: this.append,
            [`${prefixCls}-hide-icon`]: this.append  // #554
          }
        ];
      },
      inputClasses () {
        return [
          `${prefixCls}`,
          {
            [`${prefixCls}-${this.size}`]: !!this.size,
            [`${prefixCls}-disabled`]: this.disabled
          }
        ];
      },
      textareaClasses () {
        return [
          `${prefixCls}`,
          {
            [`${prefixCls}-disabled`]: this.disabled
          }
        ];
      }
    },
    methods: {
      handleEnter (event) {
        this.$emit('on-enter', event);
      },
      handleIconClick (event) {
        this.$emit('on-click', event);
      },
      handleFocus (event) {
        this.$emit('on-focus', event);
      },
      handleBlur (event) {
        this.$emit('on-blur', event);
        if (!findComponentUpward(this, ['DatePicker', 'TimePicker', 'Cascader', 'Search'])) {
          this.dispatch('FormItem', 'on-form-blur', this.currentValue);
        }
      },
      handleInput (event) {
        let value = event.target.value;
        if (this.number) value = Number.isNaN(Number(value)) ? value : Number(value);
        this.$emit('input', value);
        this.setCurrentValue(value);
        this.$emit('on-change', event);
      },
      handleChange (event) {
        this.$emit('on-input-change', event);
      },
      setCurrentValue (value) {
        if (value === this.currentValue) return;
        this.$nextTick(() => {
          this.resizeTextarea();
        });
        this.currentValue = value;
        if (!findComponentUpward(this, ['DatePicker', 'TimePicker', 'Cascader', 'Search'])) {
          this.dispatch('oolongFormItem', 'on-form-change', value);
        }
      },
      resizeTextarea () {
        const autosize = this.autosize;
        if (!autosize || this.type !== 'textarea') {
          return false;
        }

        const minRows = autosize.minRows;
        const maxRows = autosize.maxRows;

        this.textareaStyles = calcTextareaHeight(this.$refs.textarea, minRows, maxRows);
      },
      focus() {
        if (this.type === 'textarea') {
          this.$refs.textarea.focus();
        } else {
          this.$refs.input.focus();
        }
      }
    },
    watch: {
      value (val) {
        this.setCurrentValue(val);
      }
    },
    mounted () {
      if (this.type !== 'textarea') {
        this.prepend = this.$slots.prepend !== undefined;
        this.append = this.$slots.append !== undefined;
      } else {
        this.prepend = false;
        this.append = false;
      }
      this.slotReady = true;
      this.resizeTextarea();
    }
  };
</script>
